"""简化的连接管理器"""
import json
import socket
import ssl
import threading
import time
from datetime import datetime
from .config import SERVER_CONFIG, setup_logging

try:
    import websocket
except ImportError:
    print("警告: websocket-client未安装，请运行: pip install websocket-client")
    websocket = None

class ConnectionManager:
    """WebSocket连接管理器"""
    
    def __init__(self):
        self.logger = setup_logging('Connection')
        self.ws = None
        self.connected = False
        self.lock = threading.Lock()
        
        # 错误频率限制
        self.last_timeout_log_time = 0
        self.timeout_log_interval = 30  # 30秒内只记录一次超时错误
        self.timeout_count = 0
        self.timeout_count_reset_time = time.time()
    
    def connect(self):
        """连接到服务器"""
        if websocket is None:
            self.logger.error("websocket-client未安装")
            return False
            
        try:
            self.close()
            
            url = f"ws://{SERVER_CONFIG['host']}:{SERVER_CONFIG['port']}"
            self.logger.info(f"尝试连接到: {url}")
            
            # 设置WebSocket连接选项
            self.ws = websocket.create_connection(
                url,
                timeout=SERVER_CONFIG['timeout'],
                sslopt={"cert_reqs": ssl.CERT_NONE},
                # 添加更多连接选项提高稳定性
                sockopt=[
                    (socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)
                ] if hasattr(socket, 'SO_KEEPALIVE') else None
            )
            
            # 验证连接状态
            if self.ws and self.ws.connected:
                self.connected = True
                self.logger.info("WebSocket连接建立成功")
                
                # 测试连接是否真正可用
                try:
                    self.ws.ping()
                    self.logger.debug("连接测试成功")
                except Exception as ping_e:
                    self.logger.warning(f"连接测试失败: {ping_e}")

                # 启用TCP_NODELAY以降低延迟（禁用Nagle算法）
                try:
                    if hasattr(self.ws, 'sock') and self.ws.sock:
                        self.ws.sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
                        self.logger.info("已启用TCP_NODELAY以减少发送延迟")
                except Exception as sock_e:
                    self.logger.debug(f"设置TCP_NODELAY失败: {sock_e}")
                
                return True
            else:
                self.logger.error("WebSocket连接状态异常")
                self.connected = False
                return False
            
        except Exception as e:
            self.connected = False
            self.logger.error(f"WebSocket连接失败: {e}")
            self.logger.error(f"错误类型: {type(e).__name__}")
            return False
    
    def is_connected(self):
        """检查连接状态"""
        if not self.connected or self.ws is None:
            return False
        
        try:
            # 检查WebSocket连接状态
            if hasattr(self.ws, 'connected') and not self.ws.connected:
                self.logger.warning("WebSocket连接已断开")
                self.connected = False
                return False
            
            # 尝试ping测试连接
            self.ws.ping()
            return True
        except Exception as e:
            self.logger.warning(f"连接状态检查失败: {e}")
            self.connected = False
            return False
    
    def close(self):
        """关闭连接"""
        if self.ws:
            try:
                self.ws.close()
                self.logger.info("连接已关闭")
            except:
                pass
            finally:
                self.ws = None
                self.connected = False
    
    def send_json(self, data):
        """发送JSON数据"""
        if not self.is_connected():
            self.logger.error("未连接，无法发送数据")
            return False
        
        try:
            json_str = json.dumps(data, ensure_ascii=False)
            self.logger.debug(f"发送JSON数据: {json_str}")
            
            with self.lock:
                self.ws.send(json_str)
            
            self.logger.info("JSON数据发送成功")
            return True
        except Exception as e:
            self.logger.error(f"发送JSON数据失败: {e}")
            self.connected = False
            return False
    
    def send_binary(self, data):
        """发送二进制数据"""
        if not self.is_connected():
            self.logger.error("未连接，无法发送二进制数据")
            return False
        
        try:
            with self.lock:
                self.ws.send(data, websocket.ABNF.OPCODE_BINARY)
            return True
        except Exception as e:
            self.logger.error(f"发送二进制数据失败: {e}")
            self.connected = False
            return False

    def send_binary_quick(self, data, timeout=0.05):
        """发送二进制数据（尽力而为的实时模式）：
        在限定超时时间内尝试发送，超时则丢弃当前帧以避免阻塞。
        """
        if not self.is_connected():
            self.logger.error("未连接，无法发送二进制数据")
            return False

        orig_timeout = None
        try:
            # 记录原始超时设置
            if hasattr(self.ws, 'sock') and self.ws.sock:
                try:
                    orig_timeout = self.ws.sock.gettimeout()
                except Exception:
                    orig_timeout = None

            with self.lock:
                # 设置较小的发送超时，避免阻塞
                try:
                    self.ws.settimeout(float(timeout))
                except Exception:
                    pass

                self.ws.send(data, websocket.ABNF.OPCODE_BINARY)
            return True
        except Exception as e:
            # 发送超时或失败：丢弃当前帧，保持连接（除非连接已断）
            if "timed" in str(e).lower():
                self.logger.debug("视频帧发送超时，已丢弃当前帧")
            else:
                self.logger.warning(f"视频帧发送失败，已丢弃: {e}")
                # 如果是连接关闭相关错误，标记断开
                if 'closed' in str(e).lower():
                    self.connected = False
            return False
        finally:
            # 恢复原始超时设置，避免影响其他收发操作
            try:
                if orig_timeout is not None:
                    self.ws.settimeout(orig_timeout)
            except Exception:
                pass
    
    def receive_json(self, timeout=5):
        """接收JSON数据"""
        if not self.is_connected():
            self.logger.warning("连接已断开，无法接收数据")
            return None
        
        try:
            self.logger.debug(f"等待接收数据，超时时间: {timeout}秒")
            self.ws.settimeout(timeout)
            data = self.ws.recv()
            self.logger.debug(f"收到原始数据: {data}")
            
            if isinstance(data, bytes):
                data = data.decode('utf-8')
            
            json_data = json.loads(data)
            self.logger.debug(f"解析JSON成功: {json_data}")
            return json_data
        except websocket.WebSocketTimeoutException:
            # 频率限制的超时错误日志
            current_time = time.time()
            self.timeout_count += 1
            
            # 每30秒重置计数器
            if current_time - self.timeout_count_reset_time > 30:
                self.timeout_count_reset_time = current_time
                self.timeout_count = 1
            
            # 只在特定条件下记录错误日志
            should_log = (
                current_time - self.last_timeout_log_time > self.timeout_log_interval or
                self.timeout_count <= 3  # 前3次超时总是记录
            )
            
            if should_log:
                if self.timeout_count > 3:
                    self.logger.error(f"接收数据超时 ({timeout}秒) - 已发生{self.timeout_count}次超时")
                else:
                    self.logger.error(f"接收数据超时 ({timeout}秒)")
                self.last_timeout_log_time = current_time
            else:
                # 使用debug级别记录，避免频繁的错误日志
                self.logger.debug(f"接收数据超时 ({timeout}秒) - 总计{self.timeout_count}次")
            
            return None
        except json.JSONDecodeError as e:
            self.logger.error(f"JSON解析失败: {e}, 原始数据: {data}")
            return None
        except Exception as e:
            self.logger.error(f"接收数据失败: {e}")
            self.connected = False
            return None
    
    def receive_and_confirm(self, timeout=5):
        """接收消息并发送客户端确认"""
        message = self.receive_json(timeout)
        
        if message:
            # 发送客户端确认
            client_confirm = {
                "role": "hardware",
                "status": "success"
            }
            
            if self.send_json(client_confirm):
                self.logger.debug("已发送客户端确认")
            else:
                self.logger.warning("发送客户端确认失败")
        
        return message
    
    def authenticate(self, max_retries=3):
        """身份认证"""
        for attempt in range(max_retries):
            self.logger.info(f"开始身份认证 (尝试 {attempt + 1}/{max_retries})")
            
            # 发送身份确认
            auth_data = {
                "type": "connect",
                "role": "hardware"
            }
            
            self.logger.info("发送身份确认...")
            if not self.send_json(auth_data):
                self.logger.error("发送身份确认失败")
                if attempt < max_retries - 1:
                    self.logger.info("等待2秒后重试...")
                    import time
                    time.sleep(2)
                    continue
                return False
            
            # 等待服务端确认
            self.logger.info("等待服务端确认...")
            response = self.receive_json(timeout=15)  # 增加超时时间
            
            if not response:
                self.logger.error("未收到服务端确认（超时或连接断开）")
                if attempt < max_retries - 1:
                    self.logger.info("等待3秒后重试...")
                    import time
                    time.sleep(3)
                    continue
                return False
            
            self.logger.info(f"收到服务端响应: {response}")
            
            # 验证服务端确认格式
            if (response.get('role') == 'serve' and 
                response.get('status') == 'success'):
                
                self.logger.info("收到服务端确认，身份认证成功")
                
                # 发送客户端确认
                client_confirm = {
                    "role": "hardware",
                    "status": "success"
                }
                
                if self.send_json(client_confirm):
                    self.logger.info("已发送客户端确认，身份认证完成")
                    return True
                else:
                    self.logger.error("发送客户端确认失败")
                    if attempt < max_retries - 1:
                        self.logger.info("等待2秒后重试...")
                        import time
                        time.sleep(2)
                        continue
                    return False
            else:
                self.logger.error(f"身份认证失败，服务端响应格式不正确: {response}")
                self.logger.error(f"期望: role='serve', status='success'")
                self.logger.error(f"实际: role='{response.get('role')}', status='{response.get('status')}'")
                if attempt < max_retries - 1:
                    self.logger.info("等待3秒后重试...")
                    import time
                    time.sleep(3)
                    continue
                return False
        
        self.logger.error(f"身份认证失败，已尝试 {max_retries} 次")
        return False
    
    def diagnose_connection(self):
        """诊断连接问题"""
        self.logger.info("开始连接诊断...")
        
        # 1. 检查网络连通性
        import socket
        try:
            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            sock.settimeout(5)
            result = sock.connect_ex((SERVER_CONFIG['host'], SERVER_CONFIG['port']))
            sock.close()
            
            if result == 0:
                self.logger.info("✓ 网络连通性正常")
            else:
                self.logger.error(f"✗ 网络连通性失败，错误码: {result}")
                return False
        except Exception as e:
            self.logger.error(f"✗ 网络连通性测试失败: {e}")
            return False
        
        # 2. 检查WebSocket连接
        if self.ws is None:
            self.logger.error("✗ WebSocket对象未创建")
            return False
        
        # 3. 检查连接状态
        if not self.connected:
            self.logger.error("✗ 连接状态为断开")
            return False
        
        # 4. 测试数据发送
        try:
            test_data = {"type": "ping", "timestamp": str(datetime.now())}
            if self.send_json(test_data):
                self.logger.info("✓ 数据发送测试成功")
            else:
                self.logger.error("✗ 数据发送测试失败")
                return False
        except Exception as e:
            self.logger.error(f"✗ 数据发送测试异常: {e}")
            return False
        
        self.logger.info("连接诊断完成，所有测试通过")
        return True